﻿using System;
using System.Data;
using DevScope.SharePoint.Utils.BulkDelete.Configuration;
using DevScope.SharePoint.Utils.BulkDelete.Logging;
using System.Configuration;
using System.IO;

namespace DevScope.SharePoint.Utils.BulkDelete
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Arguments arguments = null;

                if (!ReadArguments(args, out arguments))
                {
                    ShowUsage();
                    return;
                }

                Logger.Log(@"Web: '{1}'
List: {0}
View fields: {5}
Query: {2}
Query options: {3}
Batch size: {4}", arguments.ListName, arguments.WebUrl, arguments.Filter.QueryAsString, arguments.Filter.QueryOptionsAsString, arguments.BatchSize, arguments.Filter.ViewFieldsAsString);
                
                int tryNumber = 1;
                
                while (tryNumber <= arguments.Retries || arguments.Retries == -1)
                {
                    try
                    {
                        DataTable dt = BulkDelete.GetListItems(arguments.WebUrl, arguments.ListName
                                        , arguments.Filter.ViewFieldsAsString, arguments.Filter.QueryAsString, arguments.Filter.QueryOptionsAsString, arguments.BatchSize);
                        
                        if (dt == null)
                        {
                            Logger.Log("Cannot find any item...");
                            break;
                        }

                        int totalItemsDeleted = 0;

                        while (dt != null)
                        {
                            Logger.Log("Deleting batch of {0} items.", dt.Rows.Count);

                            BulkDelete.DeleteListItems(dt, arguments.WebUrl, arguments.ListName);

                            Logger.Log("Batch executed with success.");

                            totalItemsDeleted += dt.Rows.Count;

                            dt.Dispose();//Dont need the DataTable, so i'll dispose it                   

                            dt = BulkDelete.GetListItems(arguments.WebUrl, arguments.ListName
                                        ,arguments.Filter.ViewFieldsAsString, arguments.Filter.QueryAsString, arguments.Filter.QueryOptionsAsString, arguments.BatchSize);
                        }

                        Logger.Log("Deleted a total of '{0}' items from list: '{1}' on web: '{2}'.", totalItemsDeleted, arguments.ListName, arguments.WebUrl);

                        break;
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex, "Error cleaning list: '{0}', Try number: {1}/{2}", arguments.ListName, tryNumber, arguments.Retries);
                        tryNumber++;
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Main");
            }            
        }

        /// <summary>
        /// Shows the usage.
        /// </summary>
        private static void ShowUsage()
        {
            Console.WriteLine(
@"Usage: BulkDelete <comands> [ <options> ]
Commands:
    {0} <Web url>
        Url to the web
    {1} <List name>
        Name of the list
Options:
    {2} <Path to the filter configuration file>
        Absolute/Relative path to the filter configuration file
        Default: No filter applied
    {3} <Batch size>
        Batch size to execute the delete
        Default: {4}
    {5} <Number of retries>
        Number of retries in case of error        
        Default: {6}
        Notes: -1 to infinite
    {7} <Help>
        Help of usage"
, Constants.Arguments.Web, Constants.Arguments.List, Constants.Arguments.Filter, Constants.Arguments.BatchSize
, Constants.DefaultValues.BatchSize, Constants.Arguments.RetryCount, Constants.DefaultValues.Retries, Constants.Arguments.Help);        
        }

        /// <summary>
        /// Reads the arguments.
        /// </summary>
        /// <param name="args">The args.</param>
        /// <param name="arguments">The arguments.</param>
        /// <returns></returns>
        private static bool ReadArguments(string[] args, out Arguments arguments)
        {
            arguments = null;

            if (args.Length == 0)
                return false;   

            if (args.Length == 1 && args[0] == Constants.Arguments.Help)
                return false;

            if (args.Length < 2)
                return false;   

            arguments = new Arguments();

            for (int i = 0; i < args.Length; i++)
            {
                switch (args[i].ToLower())
                {
                    case Constants.Arguments.Web:
                        arguments.WebUrl = args[++i];
                        break;
                    case Constants.Arguments.List:
                        arguments.ListName = args[++i];
                        break;
                    case Constants.Arguments.Filter:
                        arguments.FilterConfigFilePath = args[++i];
                        arguments.Filter = Filter.LoadFromFile(arguments.FilterConfigFilePath);
                        break;
                    case Constants.Arguments.BatchSize:
                        arguments.BatchSize = int.Parse(args[++i]);
                        break;
                    case Constants.Arguments.RetryCount:
                        arguments.Retries = int.Parse(args[++i]);
                        break;                    
                    default:
                        throw new ConfigurationErrorsException(string.Format("Invalid argument: '{0}'", args[i].ToLower()));
                }
            }

            if (string.IsNullOrEmpty(arguments.WebUrl))
            {
                Logger.Error("Must set argument '{0}'", Constants.Arguments.Web);
                return false;
            }

            if (string.IsNullOrEmpty(arguments.ListName))
            {
                Logger.Error("Must set argument '{0}'", Constants.Arguments.List);                
                return false;
            }
            
            if (arguments.Filter == null)
                arguments.Filter = new Filter();

            return true;
        }     

    }
}
